/*
** Filename: FT232SPIM.c
**
** Automatically created by Application Wizard 1.4.2
**
** Part of solution Firmware in project FT232SPIM
**
** Comments:
**
** Important: Sections between markers "FTDI:S*" and "FTDI:E*" will be overwritten by
** the Application Wizard
*/

#include "FT232SPIM.h"
#include "cli.h"
//#include "app_cli.h"
#include <string.h>
#include <stdio.h>

/* FTDI:STP Thread Prototypes */
vos_tcb_t *tcbSETUP;
vos_tcb_t *tcbREAD;

void setup();
void read();
void ft232_print(char *data);
/* FTDI:ETP */

/* FTDI:SDH Driver Handles */
VOS_HANDLE hUSBSLAVE_1; // USB Slave Port 1
VOS_HANDLE hSPI_MASTER; // SPIMaster Interface Driver
VOS_HANDLE hUSBSLAVE_FT232; // Emulates an FT232 device using the USB Slave Interface
/* FTDI:EDH */

vos_semaphore_t setupSem;

/* Declaration for IOMUx setup function */
void iomux_setup(void);

/* Main code - entry point to firmware */
void main() {
	/* FTDI:SDD Driver Declarations */
	// SPI Master configuration context
	spimaster_context_t spimContext;
	/* FTDI:EDD */

	/* FTDI:SKI Kernel Initialisation */
	vos_init(50, VOS_TICK_INTERVAL, VOS_NUMBER_DEVICES);
	vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
	vos_set_idle_thread_tcb_size(512);
	/* FTDI:EKI */

	iomux_setup();

	/* FTDI:SDI Driver Initialisation */
	// Initialise USB Slave Port 0
	usbslave_init(0, VOS_DEV_USBSLAVE_1);

	// Initialise SPI Master
	spimContext.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
	spimaster_init(VOS_DEV_SPI_MASTER,&spimContext);

	// Initialise USB Slave FT232 Driver
	usbslaveft232_init(VOS_DEV_USBSLAVE_FT232, NULL);
	/* FTDI:EDI */

	/* FTDI:SCT Thread Creation */
	tcbSETUP = vos_create_thread_ex(21, 1024, setup, "Setup", 0);
	tcbREAD = vos_create_thread_ex(20, 1024, read, "Read", 0);
	/* FTDI:ECT */

	vos_init_semaphore(&setupSem, 0);

	vos_start_scheduler();

main_loop:
	goto main_loop;
}

/* FTDI:SSP Support Functions */

VOS_HANDLE ft232_slave_attach(VOS_HANDLE hUSB, unsigned char devHostFT232)
{
	common_ioctl_cb_t ft232_iocb;
	VOS_HANDLE hSlaveFT232;

	// open FT232 driver
	hSlaveFT232 = vos_dev_open(devHostFT232);

	// attach FT232 to USB Slave port
	ft232_iocb.ioctl_code = VOS_IOCTL_USBSLAVEFT232_ATTACH;
	ft232_iocb.set.data = hUSB;
	if (vos_dev_ioctl(hSlaveFT232, &ft232_iocb) != USBSLAVE_OK)
	{
		vos_dev_close(hSlaveFT232);
		hSlaveFT232 = NULL;
	}

	return hSlaveFT232;
}

void ft232_slave_detach(VOS_HANDLE hSlaveFT232)
{
	common_ioctl_cb_t ft232_iocb;

	if (hSlaveFT232)
	{
		ft232_iocb.ioctl_code = VOS_IOCTL_USBSLAVEFT232_DETACH;

		vos_dev_ioctl(hSlaveFT232, &ft232_iocb);
		vos_dev_close(hSlaveFT232);
	}
}

/* FTDI:ESP */

void setup()
{
	// SPI Master Context
	spimaster_context_t spimasterCtx;
	// SPI Master IOCTL request block
	common_ioctl_cb_t spim_iocb;

	/* Open Handles */
	hUSBSLAVE_1 = vos_dev_open(VOS_DEV_USBSLAVE_1);
	hSPI_MASTER = vos_dev_open(VOS_DEV_SPI_MASTER);

	/* Setup SPI Master */
	// set clock phase
	spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPHA;
	spim_iocb.set.param = SPI_MASTER_SCK_CPHA_0;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
	// set clock polarity
	spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SCK_CPOL;
	spim_iocb.set.param = SPI_MASTER_SCK_CPOL_0;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
	// set data order
	spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_DATA_ORDER;
	spim_iocb.set.param = SPI_MASTER_DATA_ORDER_MSB;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
	// enable DMA
	spim_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
	spim_iocb.set = DMA_ACQUIRE_AND_RETAIN;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
	// set clock rate
	spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_SET_SCK_FREQUENCY;
	spim_iocb.set.spi_master_sck_freq = 3000000;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);
	// set auto toggle
	spim_iocb.ioctl_code = VOS_IOCTL_SPI_MASTER_AUTO_TOGGLE_SS;
	spim_iocb.set.param = SPI_MASTER_SS_AUTO_TOGGLE_ENABLE_SS_0;
	vos_dev_ioctl(hSPI_MASTER, &spim_iocb);

	/* Attach FT232 Slave */
	hUSBSLAVE_FT232 = ft232_slave_attach(hUSBSLAVE_1, VOS_DEV_USBSLAVE_FT232);

	/* Signal read thread */
	vos_signal_semaphore(&setupSem);
}

void read()
{
	common_ioctl_cb_t common_iocb;
	unsigned short dataAvail, dataRead = 0;
	unsigned char *data = NULL;
	struct shell_ctx *shell;
	struct cli_ctx_t *cli_ctx;

	vos_wait_semaphore(&setupSem);
	
	cli_ctx = cli_create("$", ft232_print);
	//cli_init(&cli_ctx);
	//cli_key(&cli_ctx, "");
	

	// Malloc the same size as the in and out endpoints...
	data = (unsigned char *)malloc(128);
	
	while (1)
	{
		// Read data in on the FT232 Slave
		common_iocb.ioctl_code = VOS_IOCTL_COMMON_GET_RX_QUEUE_STATUS;
		vos_dev_ioctl(hUSBSLAVE_FT232, &common_iocb);
		dataAvail = common_iocb.get.queue_stat;

		vos_dev_read(hUSBSLAVE_FT232, data, dataAvail, &dataRead);

		while (dataRead > 0) {
			cli_key(&cli_ctx, data);
			dataRead--;
		}
		// Write data to the SPI Master
		//vos_dev_write(hSPI_MASTER, data, dataAvail, &dataRead);

		// Read the data from the SPI Master
		//vos_dev_read(hSPI_MASTER, data, dataAvail, &dataRead);

		// Write data to the FT232 Slave
		//vos_dev_write(hUSBSLAVE_FT232, data, dataAvail, &dataRead);
	}

	free(data);
}

void ft232_print(char *data) {
	unsigned short len, dataWritten;
	
	len = strlen(data);
	vos_dev_write(hUSBSLAVE_FT232, data, len, &dataWritten);
}
